package com.changgou.service.impl;

import com.alibaba.fastjson.JSON;
import com.changgou.common.pojo.Result;
import com.changgou.goods.feign.SkuFeign;
import com.changgou.goods.pojo.Sku;
import com.changgou.pojo.SkuInfo;
import com.changgou.service.ISkuInfoService;
import com.changgou.service.dao.SkuEsMapper;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.bucket.terms.StringTerms;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.*;

@Service
public class ISkuInfoServiceImpl implements ISkuInfoService {
    @Autowired
    private SkuFeign skuFeign;
    @Autowired
    private SkuEsMapper skuEsMapper;
    @Autowired
    private ElasticsearchTemplate elasticsearchTemplate;

    @Override
    public void imPortSkuDbToEs() {
        Result<List<Sku>> byStatus = skuFeign.findByStatus("1");
        List<Sku> data = byStatus.getData();
        if (data != null && data.size() > 0) {
            List<SkuInfo> list = JSON.parseArray(JSON.toJSONString(data), SkuInfo.class);
            for (SkuInfo skuInfo : list) {
                skuInfo.setSpecMap(JSON.parseObject(skuInfo.getSpec()));
            }
            skuEsMapper.saveAll(list);
        }

    }

    @Override
    public Map search(Map<String, String> map) {
        String keywords = map.get("keywords");
        if (StringUtils.isEmpty(keywords)) {
            keywords = "华为";
        }
        NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();
        builder.addAggregation(AggregationBuilders.terms("skuCategorygroup").field("categoryName").size(100));
        builder.addAggregation(AggregationBuilders.terms("skuBrandgroup").field("brandName").size(100));
        builder.addAggregation(AggregationBuilders.terms("skuSpecgroup").field("spec.keyword").size(100));
        builder.withQuery(QueryBuilders.matchQuery("name", keywords));
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        //分类规格过滤
        String category = map.get("category");
        if (category != null) {
            boolQueryBuilder.filter(QueryBuilders.termQuery("categoryName", category));
        }
        //添加品牌过滤
        String brand = map.get("brand");
        if (brand != null) {
            boolQueryBuilder.filter(QueryBuilders.termQuery("brandName", brand));
        }
        //添加规格过滤
        for (Map.Entry<String, String> stringStringEntry : map.entrySet()) {
            String key = stringStringEntry.getKey();
            String value = stringStringEntry.getValue();
            if(key.startsWith("spec_")){
                boolQueryBuilder.filter(QueryBuilders.termQuery("specMap."+key.substring(5)+".keyword",value));
            }
        }
        //添加价格过滤范围
        String price = map.get("price");
        if(!StringUtils.isEmpty(price)){
            String[] split = price.split("-");
            if(split[1].equalsIgnoreCase("*")){
                boolQueryBuilder.filter(QueryBuilders.rangeQuery("price").gte(split[0]));
            }else{
                boolQueryBuilder.filter(QueryBuilders.rangeQuery("price").gte(split[0]).lte(split[1]));
            }
        }
        //添加 排序
        String sortField = map.get("sortField");
        String sortRule = map.get("sortRule");
        if(!StringUtils.isEmpty(sortField) && !StringUtils.isEmpty(sortRule)){
            builder.withSort(SortBuilders.fieldSort(sortField).order(SortOrder.valueOf(sortRule)));
        }
        //分页
        String pageNumString = map.get("pageNum");
        int pageNum = 1;
        if(!StringUtils.isEmpty(pageNumString)){
            pageNum = Integer.parseInt(pageNumString);
        }
        Pageable pageable = PageRequest.of(pageNum - 1, 40);
        builder.withPageable(pageable);
        builder.withFilter(boolQueryBuilder);
        NativeSearchQuery searchQuery = builder.build();
        AggregatedPage<SkuInfo> skuInfos = elasticsearchTemplate.queryForPage(searchQuery, SkuInfo.class);
        //获取分类查询结果
        List<String> categoryList = getList(skuInfos, "skuCategorygroup");
        //获取品牌查询结果
        List<String> brandList = getList(skuInfos, "skuBrandgroup");
        //获取规格查询结果
        Map<String, Set<String>> specMap = getStringSetMap(skuInfos, "skuSpecgroup");


        List<SkuInfo> content = skuInfos.getContent();
        int totalPages = skuInfos.getTotalPages();
        long totalElements = skuInfos.getTotalElements();
        Map<String, Object> map1 = new HashMap<String, Object>();
        map1.put("rows", content);
        map1.put("totalPages", totalPages);
        map1.put("total", totalElements);
        map1.put("categoryList", categoryList);
        map1.put("brandList", brandList);
        map1.put("specMap", specMap);
        return map1;
    }

    private List<String> getList(AggregatedPage<SkuInfo> skuInfos, String name) {
        StringTerms stringTerms = (StringTerms) skuInfos.getAggregation(name);
        List<String> list = new LinkedList<String>();
        if (stringTerms != null) {
            for (StringTerms.Bucket bucket : stringTerms.getBuckets()) {
                list.add(bucket.getKeyAsString());
            }
        }
        return list;
    }

    private Map<String, Set<String>> getStringSetMap(AggregatedPage<SkuInfo> skuInfos, String name) {
        StringTerms stringTerms = (StringTerms) skuInfos.getAggregation(name);
        Map<String, Set<String>> specMap = new HashMap<String, Set<String>>();
        if (stringTerms != null) {
            for (StringTerms.Bucket bucket : stringTerms.getBuckets()) {
                Map<String, String> map = JSON.parseObject(bucket.getKeyAsString(), Map.class);
                //   Set<String> set = null;
                for (Map.Entry<String, String> stringStringEntry : map.entrySet()) {
                    String key = stringStringEntry.getKey();
                    String value = stringStringEntry.getValue();
                    Set<String> values = specMap.get(key);
                    if (values == null) {
                        values = new HashSet<>();
                    }
                    values.add(value);
                    specMap.put(key, values);
                }
            }
        }
        return specMap;
    }
}
